using AnalyStock.DataManage;
namespace AnalyStock.GrapImage;
/// <summary>
///     画分时图，查看分时图
/// </summary>
public partial class ChartKline : UserControl
{
    private float TopPrice_YAxis, BottomPrice_YAxis;
    private bool IsMinutePanelVisible => MintuePricePanel.IsVisible;
    private bool IsZoom { get; set; }
    private bool IsCurrPriceAxis { get; set; } = true; //实时股价坐标系

    private void InitializePanel_ChartMintue()
    {
        MintuePricePanel.Visibility = Visibility.Hidden;
        MintuePricePanel.InitializeMouseDarg(this);
        BtnZoomMintuePanel.Click += ChangePanelZoomed_Click;
        BtnChangePriceAxis.Click += ChangeAxised_Click;
    }

    private void MintuePricePanel_OpenToClose()
    {
        if (MintuePricePanel.IsVisible)
        {
            MintuePricePanel.Visibility = Visibility.Hidden;
            return;
        }
        MintuePricePanel.Visibility = Visibility.Visible;
    }

    private void ChangePanelZoomed_Click(object sender, RoutedEventArgs e)
    {
        IsZoom = !IsZoom;
        var _zoomSizeValue = IsZoom ? 60.0 : -60.0;
        BtnZoomMintuePanel.Content = IsZoom ? "⇘" : "⇖";
        MintuePricePanel.Width += _zoomSizeValue;
        MintuePricePanel.Height += _zoomSizeValue;
        MintuePricePanel.UpdateLayout();
        PaintMintuePanel();
    }

    private void ChangeAxised_Click(object sender, RoutedEventArgs e)
    {
        IsCurrPriceAxis = !IsCurrPriceAxis;
        PaintMintuePanel();
    }

    private void PaintMintuePanel()
    {
        MintueLineCanvas.Children.Clear();
        if (currKlinedata.MinuteDatas.IsNullOrEmpty())
        {
            return;
        }
        GetMaxMinPrice_Mintue();
        PaintMarkLineOnXaxis_Mintue();
        PaintMarkLineOnYaxis_Mintue();
        PaintTimelyPriceLine_Mintue();
        PaintVolume_Mintue();
    }

    /// <summary>
    ///     涨跌停价格
    /// </summary>
    private void GetMaxMinPrice_Mintue()
    {
        var (_maxPrice_Minute, _minPrice_Minute)
                     = currKlinedata.MinuteDatas.MaxMinFloat(n => n.Price_timely);
        if (IsCurrPriceAxis) //是否实时坐标
        {
            //算法1：实时坐标系       
            TopPrice_YAxis = _maxPrice_Minute;
            BottomPrice_YAxis = _minPrice_Minute;
            return;
        }
        var _yestClose = currKlinedata.MinuteDatas.FirstOrDefault().Yestclose;
        var _v1 = MathF.Abs(_maxPrice_Minute - _yestClose);
        var _v2 = MathF.Abs(_minPrice_Minute - _yestClose);
        var _maxPriceChg = _v1 >= _v2 ? _v1 : _v2;
        var (_topChg, _bottomChg) = (_maxPriceChg / _yestClose) switch
        {
            < 0.05f => (1.05f, 0.95f),
            >= 0.05f and < 0.10f => (1.10f, 0.90f),
            >= 0.10f and < 0.15f => (1.15f, 0.85f),
            >= 0.15f and < 0.20f => (1.20f, 0.80f),
            _ => (1.20f, 0.80f)
        };
        //算法2：阶梯型坐标
        TopPrice_YAxis = _yestClose * _topChg;
        BottomPrice_YAxis = _yestClose * _bottomChg;

    }

    /// <summary>
    ///     画X轴标志线
    /// </summary>
    private void PaintMarkLineOnXaxis_Mintue()
    {
        var _countSection_high = 12;
        var _unit_price = (TopPrice_YAxis - BottomPrice_YAxis) / _countSection_high;
        var _unitSize_High_Minute = MintueLineCanvas.ActualHeight / _countSection_high;
        var _yestclose = currKlinedata.MinuteDatas.First().Yestclose;
        for (var i = 0; i < 13; i++)
        {
            var _yLine = MintueLineCanvas.ActualHeight - (i * _unitSize_High_Minute);
            new Line
            {
                X1 = 0,
                Y1 = _yLine,
                X2 = MintueLineCanvas.ActualWidth,
                Y2 = _yLine,
                Stroke = Brushes.DarkGray,
                StrokeThickness = i is 6 ? 0.4 : 0.2,
                StrokeDashArray = i is 6 ? [20, 4] : default //画虚线
            }.WithPanel(MintueLineCanvas);

            //画价格增幅刻度值
            var _priceChange = (((BottomPrice_YAxis + (i * _unit_price)) / _yestclose) - 1.00) * 100.0;
            new TextBlock
            {
                Text = $"{BottomPrice_YAxis + (i * _unit_price):F2}",
                FontSize = 7,
                Foreground = _priceChange < 0 ? Brushes.LimeGreen : Brushes.IndianRed
            }.SetPostion(_yLine - 3.50, -25.0).WithPanel(MintueLineCanvas);

            new TextBlock
            {
                Text = $"{_priceChange:F1}",
                FontSize = 7,
                Foreground = _priceChange < 0 ? Brushes.LimeGreen : Brushes.IndianRed
            }.SetPostion(_yLine - 3.50, MintueLineCanvas.ActualWidth).WithPanel(MintueLineCanvas);
        }
    }

    /// <summary>
    ///     画Y轴标志线
    /// </summary>
    private void PaintMarkLineOnYaxis_Mintue()
    {
        var _timeTable = new[] { "9:30", "10:00", "10:30", "11:00", "11:30", "13:30", "14:00", "14:30", "15:00" };
        var _unitSize_Width_Halfhour = MintueLineCanvas.ActualWidth / (_timeTable.Length - 1);
        for (var i = 0; i < _timeTable.Length; i++)
        {
            var _xLine = i * _unitSize_Width_Halfhour;
            new Line
            {
                X1 = _xLine,
                Y1 = 0,
                X2 = _xLine,
                Y2 = MintueLineCanvas.ActualHeight,
                Stroke = Brushes.DarkGray,
                StrokeThickness = 0.2
            }.WithPanel(MintueLineCanvas);
            //画时间刻度值
            new TextBlock
            {
                Text = $"{_timeTable[i]}",
                FontSize = 7,
                Foreground = Brushes.Gray
            }.SetPostion(-12.0, _xLine - 10.0).WithPanel(MintueLineCanvas);
        }
    }

    /// <summary>
    ///     画价格分时线
    /// </summary>
    private void PaintTimelyPriceLine_Mintue()
    {
        var _countMintuesOnTrading = 242; // minuteDatas.Count;
        var _unitIndexSize_Width_Mintue
            = MintueLineCanvas.ActualWidth / _countMintuesOnTrading;
        var _unitPriceSize_High_Mintue
            = MintueLineCanvas.ActualHeight / (TopPrice_YAxis - BottomPrice_YAxis);
        var _points_Timely = new PointCollection(currKlinedata.MinuteDatas.Count);
        var _points_Mean = new PointCollection(currKlinedata.MinuteDatas.Count);
        var i = 0;
        foreach (var item in currKlinedata.MinuteDatas)
        {
            var x_Point = i++ * _unitIndexSize_Width_Mintue;
            var y_PointOnTimely
                = (TopPrice_YAxis - item.Price_timely) * _unitPriceSize_High_Mintue;
            var y_PointOnMean
                = (TopPrice_YAxis - item.Price_mean) * _unitPriceSize_High_Mintue;
            _points_Timely.Add(new Point(x_Point, y_PointOnTimely));
            _points_Mean.Add(new Point(x_Point, y_PointOnMean));
        }

        _points_Timely.PolylineWithGop(MintueLineCanvas, new ShapeParam
        {
            FillColor = Colors.DeepSkyBlue,
            StrokeThickness = 0.8,
            Gop_Opacity = 0.3
        });
        _points_Mean.PolylineWithGop(MintueLineCanvas, new ShapeParam
        {
            FillColor = Colors.DarkOrange,
            StrokeThickness = 0.6,
            Gop_Opacity = 0.3,
            IsOnlyPolyline = true,
            StrokeDashArray = [10, 5]
        });
    }

    private void PaintVolume_Mintue()
    {
        var _maxVolume = currKlinedata.MinuteDatas.Max(n => n.Volume);
        if (_maxVolume is 0)
        {
            return;
        }

        var _volume_Height_Mintue = 60.0; //交易量线占60个单位像素点
        var _unitSize_Volume_Minute = _volume_Height_Mintue / _maxVolume;
        var _unitIndexSize_Width_Mintue
            = MintueLineCanvas.ActualWidth / 240; // minuteDatas.Count;
        var i = 0;
        var _lastPrice = currKlinedata.MinuteDatas.First().Yestclose;
        foreach (var item in currKlinedata.MinuteDatas)
        {
            var x_Point = i++ * _unitIndexSize_Width_Mintue;
            //交易量线
            new Line
            {
                X1 = x_Point,
                Y1 = MintueLineCanvas.ActualHeight - _volume_Height_Mintue +
                     ((_maxVolume - item.Volume) * _unitSize_Volume_Minute),
                X2 = x_Point,
                Y2 = MintueLineCanvas.ActualHeight,
                StrokeThickness = 0.3,
                Stroke = item.Price_timely > _lastPrice ? Brushes.Red
                    : item.Price_timely < _lastPrice ? Brushes.LimeGreen
                    : Brushes.DarkGray
            }.WithPanel(MintueLineCanvas);
            //保存价格值
            _lastPrice = item.Price_timely;
        }
    }
}

///
///定时更新分钟数据

public partial class ChartKline : UserControl
{


    public void PaintMintuePanel_Tick(object sender, System.Timers.ElapsedEventArgs e)
    {
        PaintMintuePanelAsync_Timer().WithCapturaException();
    }

    private async Task PaintMintuePanelAsync_Timer()
    {
        if (MintuePricePanel.IsVisible)
        {
            //加载分钟数据
            var _minutedatas =
             await currStockInfo.Ts_code?.GetMinuteDataOnTencentAsync();
            if (!_minutedatas.IsNullOrEmpty())
            {
                currKlinedata.MinuteDatas = _minutedatas;
                await MintuePricePanel.Dispatcher.InvokeAsync(() =>
                    {
                        PaintMintuePanel();
                    });
            }
        }
    }
}

